﻿using AutoMapper;
using MediatR;
using Microsoft.EntityFrameworkCore;
using WeatherHistory.Data.Entities;
using WeatherHistory.Data.Repositories.Interfaces;
using WeatherHistory.Shared.Exceptions;

namespace WeatherHistory.Api.CommandsQueries.Commands.Weathers.Create;

public class CreateWeathersCommandHandler : IRequestHandler<CreateWeathersCommandRequest, CreateWeathersCommandResponse>
{
    private readonly IMapper _mapper;
    private readonly IRegionRepository _regionRepository;
    private readonly IWeatherRepository _weatherRepository;

    public CreateWeathersCommandHandler(IMapper mapper, IWeatherRepository weatherRepository, IRegionRepository regionRepository)
    {
        _mapper = mapper;
        _weatherRepository = weatherRepository;
        _regionRepository = regionRepository;
    }

    public async Task<CreateWeathersCommandResponse> Handle(CreateWeathersCommandRequest request, CancellationToken cancellationToken)
    {
        var region = await _regionRepository
            .AsQueryable()
            .Include(x => x.Forecasts)
            .FirstOrDefaultAsync(x => x.Id == request.RegionId, cancellationToken);
        if (region == null) throw new NotFoundException($"Регион с id '{request.RegionId}' не найден");

        var newWeather = new Weather();
        newWeather.Regions = new List<Region> { region };
        newWeather.Temperature = request.Temperature;
        newWeather.Humidity = request.Humidity;
        newWeather.PrecipitationAmount = request.PrecipitationAmount;
        newWeather.WindSpeed = request.WindSpeed;
        newWeather.WeatherCondition = request.WeatherCondition;
        newWeather.MeasurementDateTime = request.MeasurementDateTime.ToUniversalTime();

        if (request.WeatherForecast != null && request.WeatherForecast.Count != 0)
        {
            var forecasts = region.Forecasts.Where(x => request.WeatherForecast.Contains(x.Id) && x.RegionId == request.RegionId).ToList();
            var invalidForecastsIds = request.WeatherForecast.Where(x => forecasts.Select(y => y.Id).Contains(x) == false).ToList();
            if (invalidForecastsIds.Count != 0) throw new NotFoundException($"Прогнозы погоды '{string.Join("', '", invalidForecastsIds)}' для региона '{request.RegionId}' не найдены");
            newWeather.Forecasts = forecasts;
        }

        await _weatherRepository.InsertAsync(newWeather, cancellationToken);
        return _mapper.Map<CreateWeathersCommandResponse>(newWeather);
    }
}